<template>
	<view class="box">
		<scroll-view id="scroll-view-content" scroll-y="true" style="height: 80vh;" :scroll-top="scrollTop">
			<view class="scr">
				<view v-for="(item,index) in recordList" :key="index" :class="item.type">

					<view>
						<view style="color: #666A73;">
							{{item.type === 'me'?'佩奇':'ai'}}
						</view>
						<view class="message" :class="item.type+'message'">
							<text v-if="item.type === 'ai'" selectable="true" class=""
								v-html="marked(item.message,{ renderer: new marked.Renderer() })">
							</text>
							<text selectable="true" v-else v-html="item.message">{{item.message}}</text>
						</view>
					</view>
				</view>
				<view class="" style="height: 50rpx;">

				</view>
			</view>
		</scroll-view>
		<view class="message-bottom">
			<textarea @confirm='confirm' @input="handleInput" class="text" v-model="TEXT"
				style="border: 1px solid gainsboro;" placeholder="请输入您想问的问题"></textarea>
			<button class="btn" style="background-color: #42B983;color: white;" @click="sendToSpark()">发送</button>
		</view>
		<view style="z-index: 99999999;" class="rem" @click="rem">
			清除记录
		</view>
		<view class="rem rem2" @click="qh">
			切换至绘画
		</view>
	</view>
</template>

<script>
	import * as base64 from "base-64"
	import CryptoJS from '../../static/crypto-js/crypto-js.js'
	import parser from '../../static/fast-xml-parser/src/parser'
	import * as utf8 from "utf8"
	import URL from 'url'
	import {
		marked
	} from 'marked';
	import DOMPurify from 'dompurify';
	import hljs from "highlight.js/lib/common";
	// 代码主体样式文件
	import 'highlight.js/styles/github.css';

	export default {
		// https://spark-api.xf-yun.com/v1.1/chat  V1.5 domain general
		// https://spark-api.xf-yun.com/v2.1/chat  V2.0 domain generalv2
		data() {
			return {
				isdz: true,
				DOMPurify,
				marked,
				scrollTop: 0,
				TEXT: '',
				// 地址必须填写，代表着大模型的版本号！！！！！！！！！！！！！！！！
				httpUrl: "https://spark-api.xf-yun.com/v3.5/chat",
				modelDomain: '', // V1.1-V3.5动态获取，高于以上版本手动指定
				APPID: 'e39397cc', // 控制台获取填写
				APISecret: 'MDc2MDZiOTgwZDExM2YwZWZhOTgwMzcz',
				APIKey: '0e5e11f2551b32e85d68e15ed39a446a',
				recordList: [{
					type: 'ai',
					message: '欢迎使用程云风ai'
				}, ],
				historyTextList: [], // 历史会话信息，由于最大token12000,可以结合实际使用，进行移出
				tempRes: '' // 临时答复保存
			}
		},
		onLoad() {
			marked.setOptions({
				renderer: new marked.Renderer(),
				highlight: function(code) {
					return hljs.highlightAuto(code).value;
				},

				pedantic: false,
				gfm: true,
				tables: true,
				breaks: false,
				sanitize: false,
				smartLists: true,
				smartypants: false,
				xhtml: false
			});
			uni.getStorage({
				key: 'recordList',
				success: (e) => {
					this.recordList = e.data
					setTimeout(() => {
						this.scrollTop = 50000000
					}, 500)
				}
			})
		},
		methods: {
			qh() {
				uni.navigateTo({
					url: '/pages/imageai/imageai'
				})
			},
			checkStringExist(str, searchStr) {
				const regex = new RegExp(searchStr);
				return regex.test(str);
			},
			handleInput(event) {
				// const is = this.checkStringExist(this.TEXT, '\n')
				// console.log(is);
				// // 检查是否是回车键触发的换行
				// if (is) {
				// 	// 如果是键盘弹起导致的换行，则阻止
				// 	this.confirm()
				// }
			},
			renderMarkdown(markdownText) {
				return md.render(markdownText)
			},
			rem() {
				uni.showModal({
					title: '提示',
					content: '确定清除所有记录吗？',
					success: (res) => {
						if (res.confirm) {
							uni.removeStorage({
								key: 'recordList'
							})
							this.recordList = [{
								type: 'ai',
								message: '欢迎使用程云风ai'
							}, ]
						} else if (res.cancel) {}
					}
				});
			},
			confirm(e) {
				this.sendToSpark()
			},
			getsctop() {
				clearInterval(this.timer)
				this.timer = setInterval(() => {
					this.scrollTop += 5
				}, 10)
			},
			async sendToSpark() {
				this.getsctop()
				this.tempRes = "";
				this.isdz = true
				const text = this.TEXT
				this.TEXT = ''
				let myUrl = await this.getWebSocketUrl(); //鉴权
				let realThis = this;
				//连接websocket
				this.socketTask = uni.connectSocket({
					url: myUrl,
					method: 'GET',

					success: res => {
						console.log(res, "ws成功连接...", myUrl)
						realThis.wsLiveFlag = true;
					}
				})
				// 发生错误
				realThis.socketTask.onError((res) => {
					console.log("连接发生错误，请检查appid是否填写", res)
				})
				// 连接成功
				realThis.socketTask.onOpen((res) => {
					// 历史会话信息
					this.historyTextList.push({
						"role": "user",
						"content": text
					})
					// 参数
					let params = {
						"header": {
							"app_id": this.APPID,
							"uid": "aef9f963-7"
						},
						"parameter": {
							"chat": {
								"domain": this.modelDomain,
								"temperature": 0.5,
								"max_tokens": 1024
							}
						},
						"payload": {
							"message": {
								"text": this.historyTextList
							}
						}
					};
					this.recordList.push({
						type: 'me',
						message: text
					})
					this.recordList.push({
						type: 'ai',
						message: ''
					})
					this.recordList[this.recordList.length - 1].message = ''
					// 发送
					realThis.socketTask.send({ // 发送消息，，都用uni的官方版本
						data: JSON.stringify(params),
						success() {}
					});
				});
				this.arrList = []
				this.index = 0
				this.isStart = true
				clearInterval(this.timer3)
				// 接受到消息时
				realThis.socketTask.onMessage((res) => {
					let obj = JSON.parse(res.data)
					let dataArray = obj.payload.choices.text;
					let str = ''
					for (let i = 0; i < dataArray.length; i++) {
						str += dataArray[i].content
					}
					// 没有打字动画
					realThis.tempRes += str
					realThis.recordList[realThis.recordList.length - 1].message = realThis.tempRes +
						'<span class="cursor2"></span>'


					// 打字动画
					// this.arrList.push(str)
					// clearInterval(this.timer3)
					// this.timer3 = setInterval(() => {
					// 	if (this.isStart) {
					// 		this.getText()
					// 	}
					// }, 50)
					// end
					let temp = JSON.parse(res.data)
					if (temp.header.code !== 0) {
						console.log(`${temp.header.code}:${temp.message}`);
						realThis.socketTask.close({
							success(res) {
								clearInterval(this.timer)
								realThis.wsLiveFlag = false;
							},
							fail(err) {
								clearInterval(this.timer)
							}
						})
					}
					if (temp.header.code === 0) {
						if (res.data && temp.header.status === 2) {
							// this.messageEnd()
							if (realThis.arrList.length - 1 <= realThis.index) {
								this.messageEnd()
							}
							setTimeout(() => {

								realThis.socketTask.close({
									success(res) {
										this.isdz = false
									},
									fail(err) {}
								})
							}, 1000)
						}
					}
				})

			},

			messageEnd() {

				clearInterval(this.timer)
				clearInterval(this.timer3)

				this.recordList[this.recordList.length - 1].message = this.tempRes
				uni.setStorage({
					key: 'recordList',
					data: this.recordList
				})
				this.historyTextList.push({
					"role": "assistant",
					"content": this.tempRes
				})

			},

			getText() {
				let realThis = this
				realThis.isStart = false
				let text = realThis.arrList[realThis.index]
				console.log(realThis.arrList);
				realThis.tempRes = realThis.tempRes + text
				let index = 0
				if (!text) {
					realThis.isStart = true
					return
				}

				function type() {
					if (index < text.length) {
						console.log(realThis.arrList.length <= realThis.index);
						realThis.recordList[realThis.recordList.length - 1].message = realThis
							.tempRes + text[index] +
							'<span class="cursor2"></span>'
						index++;
						setTimeout(type, 50); // 设置打字速度，数值越小速度越快
					} else {
						console.log(realThis.arrList.length <= realThis.index);
						if (realThis.arrList.length <= realThis.index) {
							this.messageEnd()
							return
						}
						realThis.isStart = true
						realThis.index += 1


					}
				}
				type();
			},
			// 鉴权 --- 通用的方法
			getWebSocketUrl() {
				var httpUrlHost = (this.httpUrl).substring(8, 28);
				var httpUrlPath = (this.httpUrl).substring(28);
				switch (httpUrlPath) {
					case "/v1.1/chat":
						this.modelDomain = "general";
						break;
					case "/v2.1/chat":
						this.modelDomain = "generalv2";
						break;
					case "/v3.1/chat":
						this.modelDomain = "generalv3";
						break;
					case "/v3.5/chat":
						this.modelDomain = "generalv3.5";
						break;
				}

				return new Promise((resolve, reject) => {
					// https://spark-api.xf-yun.com/v1.1/chat  V1.5 domain general
					// https://spark-api.xf-yun.com/v2.1/chat  V2.0 domain generalv2
					var url = "wss://" + httpUrlHost + httpUrlPath;
					var host = "spark-api.xf-yun.com";
					var apiKeyName = "api_key";
					var date = new Date().toGMTString();
					var algorithm = "hmac-sha256";
					var headers = "host date request-line";
					var signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${httpUrlPath} HTTP/1.1`;
					var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, this.APISecret);
					var signature = CryptoJS.enc.Base64.stringify(signatureSha);
					var authorizationOrigin =
						`${apiKeyName}="${this.APIKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
					var authorization = base64.encode(authorizationOrigin);
					url = `${url}?authorization=${authorization}&date=${encodeURI(date)}&host=${host}`;

					resolve(url); // 主要是返回地址
				});
			},
		}
	}
</script>

<style lang="scss">
	.cursor2 {
		position: absolute;
		display: inline-block;
		width: 2px;
		height: 16px;
		background-color: #fff;
		animation: blink 1s infinite;
		transform: translate(2px, 3px);
	}

	@keyframes blink {

		0%,
		100% {
			opacity: 1;
		}

		50% {
			opacity: 0;
		}
	}

	.rem {
		position: fixed;
		top: 0.8%;
		right: 1%;
		// background-color: red;
		color: red;
		font-weight: 700;
		padding: 10rpx;
		border-radius: 15rpx;

	}

	.rem2 {
		left: 1%;
		color: #fff;
		z-index: 99999;
		display: inline-block;
	}

	scroll-view ::-webkit-scrollbar {
		display: none;
		width: 0;
		height: 0;
		color: transparent;
	}


	.box {
		margin: 30rpx;
	}

	.text {
		padding: 30rpx;
		margin-bottom: 30rpx;
	}

	.scr {
		content-visibility: auto;
		display: flex;
		flex-flow: column;
	}

	.message {
		display: inline-block;
		padding: 20rpx;
		background-color: #42B983;
		border-radius: 15rpx;
		margin-top: 15rpx;
		color: #fff;

	}

	.message-bottom {
		background-color: #fff;
		width: 100vw;
		position: fixed;
		bottom: 0;
		display: flex;
		left: 0;
		padding-left: 20rpx;
		padding-top: 20rpx;
		justify-content: space-between;
		align-items: center;

		.text {
			height: 100rpx;
			flex: 3;
			border-radius: 15rpx;
		}

		.btn {
			flex: 1;
			height: 100rpx;
			margin-right: 40rpx;
			margin-left: 15rpx;
		}

	}

	.me {
		display: inline-block;
		text-align: right;
	}

	.aimessage {
		background-color: #00aaff;
	}

	.ai {
		display: inline-block;
	}
</style>
